package com.bby.user.aop;

import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import com.bby.common.aop.ParseToken;
import com.bby.common.utils.R;
import com.bby.common.utils.StatusCode;
import com.bby.user.manager.TokenManager;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

/**
 * <p>登录转态查询，Controller 中 带 ParseToken 注解的函数将会进行token->userId的装换</p>
 * <p>token从headers中获取，userId在函数的第一个参数中。</p>
 * <p>ParseToken 注解中的 require 控制是否必须登录</p>
 */
@Component
@Aspect
public class LoginCheckAop {
    @Pointcut("within(com.bby.user.controller.*) && @annotation(com.bby.common.aop.ParseToken)")
    public void pointCut(){}


    Logger logger = LoggerFactory.getLogger(this.getClass());
    private final TokenManager tokenManager;
    public LoginCheckAop(TokenManager tokenManager) {
        this.tokenManager = tokenManager;
    }

    @Around("pointCut() && @annotation(parseToken)")
    public Object around(ProceedingJoinPoint pjp, ParseToken parseToken) throws Throwable {
        ServletRequestAttributes attributes = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes());
        Object[] args = pjp.getArgs();
        if (attributes == null || args.length<1){
            return R.error(StatusCode.INPUT_ERROR,"参数错误");
        }
        logger.debug("parseToken={}",parseToken);
        String token = attributes.getRequest().getHeader("token");
        String userId = tokenManager.readUserId(token);
        args[0] = userId;
        logger.debug("{} => token={}",pjp.getSignature().getName(),token);
        logger.debug("参数：{}", ArrayUtil.toString(args));
        if (parseToken.require() && ObjectUtil.isEmpty(userId)){
            return R.error(StatusCode.NOT_LOGIN,"抱歉，您没有登录！");
        }
        return pjp.proceed(args);
    }
}
